package com.szml.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.szml.user.feign.PermissionServiceClient;
import com.szml.user.result.PageResult;
import com.szml.user.result.Result;
import com.szml.user.dto.*;
import com.szml.user.entity.User;
import com.szml.user.mapper.UserMapper;
import com.szml.user.service.UserService;
import com.szml.user.utils.IPUtils;
import com.szml.user.utils.JWTUtils;
import com.szml.user.vo.ResetPasswordVO;
import com.szml.user.vo.UserInfoVO;
import com.szml.user.vo.UserUpdateVO;

import io.seata.spring.annotation.GlobalTransactional;

import javax.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Author limin
 * @date 2025-06-19 11:44
 * @description
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private PermissionServiceClient permissionServiceClient;



    /**
     * 用户注册
     * @param userRegisterDTO
     * @return
     */
    @Override
    @GlobalTransactional
    public Result<String> register(UserRegisterDTO userRegisterDTO, HttpServletRequest request) {
        //检查用户名是否存在
        User existingUser = userMapper.selectByUsername(userRegisterDTO.getUsername());
        if (existingUser != null) {
            return Result.error(400,"用户名已存在");
        }

        //创建新用户
        User user = new User();
        BeanUtils.copyProperties(userRegisterDTO, user);
        user.setGmtCreate(LocalDateTime.now());

        //插入数据库
        int ret = userMapper.insert(user);
        if(ret != 1){
            return Result.error(500,"插入用户注册信息失败");
        }
        user = userMapper.selectByUsername(user.getUsername());
        if(user.getUserId()!=null){
            //rpc调用接口为新用户绑定默认角色（user）
            permissionServiceClient.bindDefaultRole(user.getUserId());
        }else {
            log.error("用户ID未生成，用户名: {}", user.getUsername());
            throw new RuntimeException("用户id未生成");
        }

        //在userdb中也要同步数据
        String roleCode = userMapper.selectRoleIdByRoleCode();
        userMapper.insertUserWithRoleId(user.getUserId(),roleCode);

        //生成LogEvent对象
        LogEvent logEvent = new LogEvent();
        logEvent.setUserId(user.getUserId());
        logEvent.setAction("用户注册");
        //获取ip
        String ip = IPUtils.getClientIpv4(request);
        logEvent.setIp(ip);
        logEvent.setDetail("用户 [" + user.getUsername() + "] 注册成功");

        //发送注册消息到MQ   topic: REGISTER:tag
        //将logEvent转成JSON
        String message = JSON.toJSONString(logEvent);
        rocketMQTemplate.syncSend("REGISTER:register",message);//序列化之后发送

        return Result.success("注册成功");
    }

    /**
     * 用户登录
     * @param userLoginDTO
     * @return
     */
    @GlobalTransactional
    public Result<String> login(UserLoginDTO userLoginDTO,HttpServletRequest request) {
        User user = userMapper.selectByUsername(userLoginDTO.getUsername());

        if(user == null){
            return Result.error(400,"用户不存在");
        }
        if(!user.getPassword().equals(userLoginDTO.getPassword())){
            return Result.error(400,"密码错误");
        }
        String token = JWTUtils.getToken(user.getUserId(),user.getUsername(), user.getPassword());

        //生成LogEvent对象
        LogEvent logEvent = new LogEvent();
        logEvent.setUserId(user.getUserId());
        logEvent.setAction("用户登录");
        //获取ip
        String ip = IPUtils.getClientIpv4(request);
        logEvent.setIp(ip);
        logEvent.setDetail("用户 [" + user.getUsername() + "] 登录");

        //发送注册消息到MQ   topic: REGISTER:tag
        //将logEvent转成JSON
        String message = JSON.toJSONString(logEvent);
        rocketMQTemplate.syncSend("REGISTER:login",message);//序列化之后发送

        return Result.success(token);
    }

    /**
     * 分页展示用户信息
     * @param userPageQueryDTO
     * @param token
     * @return
     */
    @Override
    @GlobalTransactional
    public PageResult userList(UserPageQueryDTO userPageQueryDTO, String token) {
        //通过token获取当前userId
        Long currentUserId = JWTUtils.getUserId(token);

        //通过userId获得roleId
//        Integer roleId = userMapper.selectRoleIdByUserId(currentUserId);

        //通过rpc接口实现(通过userId获得roleCode)
        String roleCode = permissionServiceClient.getUserRoleCode(currentUserId);

        if (roleCode == null) {
            throw new RuntimeException("用户角色不存在");
        }

        //设置分页参数
        PageHelper.startPage(userPageQueryDTO.getPageNum(),userPageQueryDTO.getPageSize());

        //不同角色查看不同用户列表
        List<UserInfoVO> userList = null;
        switch (roleCode != null ? roleCode.trim() : "") {
            case "super_admin" : //super_admin超管
                userList = userMapper.selectAllUsers(userPageQueryDTO); // 查所有用户
                break;
            case "user" :  //user普通用户
                userList = userMapper.selectUsersById(userPageQueryDTO,currentUserId); // 只查自己
                break;
            case "admin" :  //admin管理员
                userList = userMapper.selectNormalUsers(userPageQueryDTO); // 只查普通用户
                break;
            default:
                throw new RuntimeException("未知角色类型: "+roleCode);
        }

        PageInfo<UserInfoVO> pageInfo = new PageInfo<>(userList);
        return new PageResult(pageInfo.getTotal(), pageInfo.getList());
    }


    /**
     * 通过userId获得用户信息（分权限）
     * @param userId
     * @param token
     * @return
     */
    @Override
    @GlobalTransactional
    public Result<UserInfoVO> getUserInfo(Long userId,String token) {
        //通过token获取当前userId
        Long currentUserId = JWTUtils.getUserId(token);
        if (currentUserId == null) {
            throw new RuntimeException("无效的token");
        }
        //通过userId获得roleCode
//        String roleCode = userMapper.selectRoleCodeIdByUserId(currentUserId);

        //通过rpc接口实现(通过userId获得roleCode)
        String roleCode = permissionServiceClient.getUserRoleCode(currentUserId);

        if (roleCode == null) {
            throw new RuntimeException("用户角色不存在");
        }

        UserInfoVO targetUser = userMapper.selectUserInfoById(userId);

        Integer targetUserRoleId = userMapper.selectRoleIdByUserId(userId);
        String targetUserRoleCode = userMapper.selectRoleCodeByRoleId(targetUserRoleId);

        //普通用户
        if("user".equals(roleCode) && !currentUserId.equals(userId)){
            throw new RuntimeException("普通用户无权查看其他用户信息");
        }

        //管理员 (只能查看普通用户，如果是超管和管理员就抛异常)
        if("admin".equals(roleCode)){
            if("super_admin".equals(targetUserRoleCode)||"admin".equals(targetUserRoleCode)){
                throw new RuntimeException("管理员只能查看普通用户信息");
            }
        }
        return Result.success(targetUser);
    }

    /**
     * 通过useId修改用户信息（分权限）
     * @param userId
     * @param userUpdateDTO
     * @param token
     */
    @Override
    @GlobalTransactional
    public Result<UserUpdateVO> updateUserInfo(Long userId, UserUpdateDTO userUpdateDTO, String token,HttpServletRequest request) {//通过token获取当前用户userId
        Long currentUserId = JWTUtils.getUserId(token);

        //查用户未修改前的数据
        User oldUser = userMapper.selectUserById(userId);


        if (currentUserId == null) {
            throw new RuntimeException("无效的token");
        }
        //通过userId获得roleCode
//        String roleCode = userMapper.selectRoleCodeIdByUserId(currentUserId);

        //通过rpc接口实现
        String roleCode = permissionServiceClient.getUserRoleCode(currentUserId);

        if (roleCode == null) {
            throw new RuntimeException("用户角色不存在");
        }

        UserInfoVO targetUser = userMapper.selectUserInfoById(userId);
        Integer targetUserRoleId = userMapper.selectRoleIdByUserId(userId);
        String targetUserRoleCode = userMapper.selectRoleCodeByRoleId(targetUserRoleId);
        //普通用户
        if("user".equals(roleCode) && !currentUserId.equals(userId)){
            throw new RuntimeException("普通用户无权修改其他用户信息");
        }

        //管理员 (只能修改普通用户，如果是超管和管理员就抛异常)
        if("admin".equals(roleCode)){
            if(!"user".equals(targetUserRoleCode)){
                throw new RuntimeException("管理员只能修改普通用户信息");
            }
        }

        //将对象的属性值更新到数据库
        int ret = userMapper.updateUserById(userUpdateDTO,userId);

        if(ret != 1){
            throw new RuntimeException("更新用户信息失败");
        }
        //将更新后的用户对象拷贝到VO对象
        UserUpdateVO userUpdateVO = new UserUpdateVO();
        BeanUtils.copyProperties(userUpdateDTO, userUpdateVO);

        //生成LogEvent对象
        LogEvent logEvent = new LogEvent();
        logEvent.setUserId(userId);
        logEvent.setAction("修改用户信息");
        //获取ip
        String ip = IPUtils.getClientIpv4(request);
        logEvent.setIp(ip);
        logEvent.setDetail("修改用户 ["+oldUser.getUsername()+"] 的信息, {field:'email','old':'"+oldUser.getEmail()+"','new':'"+userUpdateVO.getEmail()+"';"+
                "field:'phone','old':'"+oldUser.getPhone()+"','new':'"+userUpdateVO.getPhone()+"'"
                +"}" );

        //发送注册消息到MQ   topic: REGISTER:tag
        //将logEvent转成JSON
        String message = JSON.toJSONString(logEvent);
        rocketMQTemplate.syncSend("REGISTER:update",message);//序列化之后发送

        return Result.success(userUpdateVO);
    }

    /**
     * 重置密码（分权）
     * @param resetPasswordDTO
     * @param token
     * @return
     */
    @Override
    @GlobalTransactional
    public Result<ResetPasswordVO> resetPassword(ResetPasswordDTO resetPasswordDTO, String token,HttpServletRequest request) {
        //通过token获取当前用户userId
        Long currentUserId = JWTUtils.getUserId(token);
        if (currentUserId == null) {
            throw new RuntimeException("无效的token");
        }
        //通过userId获得roleCode
//        String roleCode = userMapper.selectRoleCodeIdByUserId(currentUserId);

        //通过rpc接口实现
        String roleCode = permissionServiceClient.getUserRoleCode(currentUserId);

        if (roleCode == null) {
            throw new RuntimeException("用户角色不存在");
        }

        String targetUserName = resetPasswordDTO.getUsername();
        UserInfoVO targetUser = userMapper.selectUserInfoByUsername(targetUserName);
        Integer targetUserRoleId = userMapper.selectRoleIdByUserId(targetUser.getUserId());
        String targetUserRoleCode = userMapper.selectRoleCodeByRoleId(targetUserRoleId);

        //要修改密码的用户对应的id
        Long userId = targetUser.getUserId();

        //查看旧密码
        String oldPassword = userMapper.selectPasswordById(userId);

        //普通用户
        if("user".equals(roleCode) && !currentUserId.equals(userId)){
            throw new RuntimeException("普通用户无权修改其他用户密码");
        }

        //管理员 (只能查看普通用户，如果是超管和管理员就抛异常)
        if("admin".equals(roleCode)){
            if(!"user".equals(targetUserRoleCode)){
                throw new RuntimeException("管理员只能修改普通用户密码");
            }
        }

        //将对象的属性值更新到数据库
        int ret = userMapper.resetPasswordByUserId(resetPasswordDTO,userId);

        if(ret != 1){
            throw new RuntimeException("重置用户密码失败");
        }
        //将更新后的用户对象拷贝到VO对象
        ResetPasswordVO resetPasswordVO = new ResetPasswordVO();
        BeanUtils.copyProperties(resetPasswordDTO, resetPasswordVO);

        //生成LogEvent对象
        LogEvent logEvent = new LogEvent();
        logEvent.setUserId(userId);
        logEvent.setAction("修改用户密码");
        //获取ip
        String ip = IPUtils.getClientIpv4(request);
        logEvent.setIp(ip);
        logEvent.setDetail("重置用户 ["+targetUser.getUsername()+"] 的密码, {field:'password','old':'"+ oldPassword +"','new':'"+resetPasswordVO.getPassword()+"'"+"}");

        //发送注册消息到MQ   topic: REGISTER:tag
        //将logEvent转成JSON
        String message = JSON.toJSONString(logEvent);
        rocketMQTemplate.syncSend("REGISTER:update",message);//序列化之后发送

        return Result.success(resetPasswordVO);
    }


}
